package com.tian.jobhandler;

import com.alibaba.fastjson.JSON;
import com.tian.entity.ChargeActiveUser;
import com.tian.entity.ChargeSystemMessage;
import com.tian.entity.ChargeSystemMessageContent;
import com.tian.mapper.ChargeActiveUserMapper;
import com.tian.mapper.ChargeSystemMessageContentMapper;
import com.tian.mapper.ChargeSystemMessageMapper;
import com.tian.util.ChargeMarketRedisKeyPrefix;
import com.tian.util.ConstantsUtil;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * {@code @description:} 给用户发站内信（通知去领取优惠券）
 *
 * @author tianwc 公众号：Java后端技术全栈
 * 在线刷题 1200+java面试题和1000+篇技术文章：<a href="https://woaijava.cc/">博客地址</a>
 * {@code @date:} 2024-08-06 20:10
 * {@code @version:} 1.0
 */
@Slf4j
@Component
public class SendSystemMessage4UserCouponJob {
    @Resource
    private ChargeSystemMessageMapper chargeSystemMessageMapper;
    @Resource
    private ChargeSystemMessageContentMapper chargeSystemMessageContentMapper;
    @Resource
    private ChargeActiveUserMapper chargeActiveUserMapper;
    @Resource
    private RedissonClient redissonClient;

    @Transactional
    @XxlJob("sendSystemMessage4UserCouponJob")
    public void process() {
        log.info("给用户发站内信（通知去领取优惠券）");
        XxlJobHelper.log(" start 给用户发站内信（通知去领取优惠券）");
        ChargeSystemMessageContent chargeSystemMessageContent = chargeSystemMessageContentMapper.selectByPrimaryKey(1);

        long countActiveUser = chargeActiveUserMapper.countActiveUser(new Date());
        for (long i = 0; i < countActiveUser; ) {
            // 每次处理50条
            List<ChargeActiveUser> chargeActiveUsers = chargeActiveUserMapper.selectActiveUser(new Date(), i, 50);
            chargeActiveUsers.forEach(chargeActiveUser -> {
                ChargeSystemMessage chargeSystemMessage = new ChargeSystemMessage();
                chargeSystemMessage.setMessageId(chargeSystemMessageContent.getId());
                chargeSystemMessage.setUserId(chargeActiveUser.getUserId());
                chargeSystemMessage.setSendTime(new Date());
                chargeSystemMessage.setIsRead(0);
                chargeSystemMessageMapper.insert(chargeSystemMessage);
                chargeActiveUser.setStatus(1);
                chargeActiveUserMapper.updateByPrimaryKey(chargeActiveUser);
                RList<Long> list = redissonClient.getList(ChargeMarketRedisKeyPrefix.USER_SYSTEM_MESSAGE_LIST_KEY + chargeSystemMessage.getUserId());
                list.add(chargeSystemMessage.getId());
                RMap<Long, String> map = redissonClient.getMap(ChargeMarketRedisKeyPrefix.USER_SYSTEM_MESSAGE_MAP_KEY + chargeSystemMessage.getUserId());
                map.put(chargeSystemMessage.getId(), JSON.toJSONString(chargeSystemMessage));
                //只保留3个月时间内的站内信，在启动一个定时任务
                RScoredSortedSet<String> scoredSortedSet = redissonClient.getScoredSortedSet(ChargeMarketRedisKeyPrefix.USER_SYSTEM_MESSAGE_SET_KEY);
                LocalDateTime expiredDateTime = chargeSystemMessage.getSendTime().toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDateTime()
                        .plusMonths(3);  // 添加 3 个月
                Date expired = Date.from(expiredDateTime.atZone(ZoneId.systemDefault()).toInstant());
                String value = chargeSystemMessage.getId() + ConstantsUtil.SET_MESSAGE_SPLIT + expired.getTime()+ConstantsUtil.SET_MESSAGE_SPLIT + chargeSystemMessage.getUserId();
                scoredSortedSet.add(expired.getTime(), value);
            });
            i = i + 50;
        }
        chargeActiveUserMapper.selectActiveUser(new Date(), 0L, 50);

        XxlJobHelper.log(" end 给用户发站内信（通知去领取优惠券）");
    }
}
